Angular路由之间共享数据时如何避免Observable的痛苦?

How to avoid the pain of Observable when sharing data between routes in Angular?

当我们希望在路由之间共享数据时,唯一可行的解​​决方案似乎是使用服务。由于我们希望数据在更新时在视图中重新呈现,因此我们必须使用 BehaviorSubject.

所以,如果我错了,请纠正我,但一个简单的组件将如下所示:

@Component({
    selector: 'user-info',
    template: `
        {{($user | async).firstName}}
        <button (click)="updateName()"></button>
    `
})
export class UserInfoComponent {

    private $user;
    private subscribe;

    constructor(private service: UserService) {
        this.user$ = this.service.get();
    }

    updateName() {
        this.subscribe = this.service.get().subscribe(user => 
            this.service.update({...user, firstName: 'new-name'})
        );
    }

    ngOnDestroy() {
        this.subscribe.unsubscribe();
    }
}

这听起来真的很令人沮丧,因为如果我们不使用路由器,我们可以只使用 <user-info [user]="user | async"></user-info> 调用组件,这样会更干净:

@Component({
    selector: 'user-info',
    template: `
        {{user.lastName}}
        <button (click)="updateName()"></button>
    `
})
export class UserInfo2Component {

    @Input() user: User;

    constructor(private service: UserService) {}

    updateName() {
        this.service.update({...user, lastName: 'new-name'});
    }
}

所以我的问题是:为什么在路由之间共享数据如此困难?有没有我可能错过的更好的解决方案?

您可以使用 ngrx 来避免使用可观察对象。它基于 redux 概念。

通过这种方式,您可以将数据设置到商店,在您的路线中传递一些 id,并在下一个路线中使用该 id 从商店获取数据。现在,store 是这里唯一的数据源,你不需要在路由之间传递数据,每个路由都可以将数据设置到 store,其他路由可以从 store 访问它。

在此处阅读更多相关信息:为什么使用 NGRX 而不是使用可观察对象的构造函数注入服务?

你的错误是在组件中处理更新逻辑,而不是在服务中。

尝试这样的事情:

user.service

import { Component, Input } from '@angular/core';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';

export class UserService {
  private user = new BehaviorSubject({
    firstName: 'Tomasz'
  })

  user$ = this.user.asObservable();

  update(user: any) {
    this.user.next({
      ...this.user.getValue(),
      ...user
    })
  }
}

app.component.ts

import { Component } from '@angular/core';
import {UserService} from './user.service';

@Component({
  selector: 'my-app',
  template: `
  <input (keydown.enter)="updateUser(input.value); input.value=''" #input>

  {{ user$ | async | json }}
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  user$;

  constructor(private userService: UserService) {
    this.user$ = this.userService.user$;
  }

  updateUser(firstName: string) {
    this.userService.update({ firstName });
  }
}

Live demo